import Taro from '@tarojs/taro'

export interface RequestOptions {
  url: string
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE'
  data?: any
  header?: Record<string, string>
  timeout?: number
}

export interface ApiResponse<T = any> {
  code: number
  message: string
  data: T
}

class RequestManager {
  private baseURL: string = ''
  private defaultHeaders: Record<string, string> = {
    'Content-Type': 'application/json'
  }
  private timeout: number = 10000

  setBaseURL(url: string) {
    this.baseURL = url
  }

  setDefaultHeaders(headers: Record<string, string>) {
    this.defaultHeaders = { ...this.defaultHeaders, ...headers }
  }

  setTimeout(timeout: number) {
    this.timeout = timeout
  }

  setToken(token: string) {
    this.setDefaultHeaders({ Authorization: `Bearer ${token}` })
  }

  removeToken() {
    const { Authorization, ...rest } = this.defaultHeaders
    this.defaultHeaders = rest
  }

  private handleResponse<T>(response: any): ApiResponse<T> {
    const { statusCode, data } = response

    if (statusCode >= 200 && statusCode < 300) {
      return data
    }

    throw new Error(data?.message || `HTTP Error: ${statusCode}`)
  }

  private showError(message: string) {
    Taro.showToast({
      title: message,
      icon: 'none',
      duration: 2000
    })
  }

  async request<T = any>(options: RequestOptions): Promise<ApiResponse<T>> {
    const {
      url,
      method = 'GET',
      data,
      header = {},
      timeout = this.timeout
    } = options

    const fullUrl = url.startsWith('http') ? url : `${this.baseURL}${url}`

    try {
      Taro.showLoading({ title: '请求中...' })

      const response = await Taro.request({
        url: fullUrl,
        method,
        data,
        header: { ...this.defaultHeaders, ...header },
        timeout
      })

      Taro.hideLoading()
      return this.handleResponse<T>(response)
    } catch (error: any) {
      Taro.hideLoading()

      const errorMessage = error.message || '网络请求失败'
      this.showError(errorMessage)

      throw error
    }
  }

  get<T = any>(url: string, data?: any, options: Omit<RequestOptions, 'url' | 'method' | 'data'> = {}): Promise<ApiResponse<T>> {
    return this.request<T>({ url, method: 'GET', data, ...options })
  }

  post<T = any>(url: string, data?: any, options: Omit<RequestOptions, 'url' | 'method' | 'data'> = {}): Promise<ApiResponse<T>> {
    return this.request<T>({ url, method: 'POST', data, ...options })
  }

  put<T = any>(url: string, data?: any, options: Omit<RequestOptions, 'url' | 'method' | 'data'> = {}): Promise<ApiResponse<T>> {
    return this.request<T>({ url, method: 'PUT', data, ...options })
  }

  delete<T = any>(url: string, data?: any, options: Omit<RequestOptions, 'url' | 'method' | 'data'> = {}): Promise<ApiResponse<T>> {
    return this.request<T>({ url, method: 'DELETE', data, ...options })
  }
}

export const request = new RequestManager()
export default request